package com.yangrd.airship.sys.web.config;

import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yangrd
 * @date 2021/11/25
 */
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注册Sa-Token的注解拦截器，打开注解式鉴权功能

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        注册注解拦截器，并排除不需要注解鉴权的接口地址(与登录拦截器无关)
        registry.addInterceptor(new RolesAllowedSaAnnotationInterceptor()).addPathPatterns("/**");
    }

    static class RolesAllowedSaAnnotationInterceptor extends SaAnnotationInterceptor {

        static final String ROLE_PREFIX = "ROLE_";

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                Method method = ((HandlerMethod) handler).getMethod();
                RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
                if (Objects.nonNull(rolesAllowed)) {
                    String[] roles = Stream.of(rolesAllowed.value()).filter(o -> o.startsWith(ROLE_PREFIX)).collect(Collectors.toList()).toArray(new String[]{});
                    if (roles.length > 0) {
                        StpUtil.checkRoleOr(roles);
                    }
                    String[] permissions = Stream.of(rolesAllowed.value()).filter(o -> !o.startsWith(ROLE_PREFIX)).collect(Collectors.toList()).toArray(new String[]{});
                    if (permissions.length > 0) {
                        StpUtil.checkPermissionOr(permissions);
                    }
                }
                return super.preHandle(request, response, handler);
            } else {
                return true;
            }
        }
    }

}
